import 'dart:convert';

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';

const channelMethod = "channel_method";
const channelEvent = "channel_event";

abstract class BaseNative {
  final String _methodChannelName;

  @protected
  final String? eventChannelName;

  // native call flutter
  EventChannel? _eventPlugin;

  // flutter invoke native
  MethodChannel? _methodChannel;

  BaseNative(this._methodChannelName, {this.eventChannelName}) {
    _methodChannel = MethodChannel(_methodChannelName);
    if (null != eventChannelName && "" != eventChannelName) {
      _eventPlugin = EventChannel(eventChannelName ?? "");
      _eventPlugin?.receiveBroadcastStream().listen(_onEvent, onError: onError);
    }
  }

  @protected
  Future<T?> nativeMethod<T>(String methodName, {Map<String, dynamic>? param}) async {
    if (param == null) {
      return await _methodChannel?.invokeMethod<T>(methodName);
    } else {
      return await _methodChannel?.invokeMethod<T>(methodName, param);
    }
  }

  void _onEvent(Object? event) {
    if (null != event && event.toString().isNotEmpty) {
      var channelEvent = ChannelEvent.fromJson(json.decode(event.toString()));
      onEvent(channelEvent);
    }
  }

  // native call flutter event
  // if has event, override this method
  void onEvent(ChannelEvent channelEvent) {}

  void onError(Object error) {}
}

class ChannelEvent {
  String? content; // native2flutter 事件内容 json
  String? title; // 事件标题

  // 事件附加内容，如send message result，返回的messageModel json str
  String? content1;

  ChannelEvent({this.content, this.title, this.content1});

  @override
  String toString() {
    return 'ChannelEvent{content: $content, title: $title, content1: $content1}';
  }

  ChannelEvent.fromJson(Map<String, dynamic> json) {
    content = json['content'];
    content1 = json['content1'];
    title = json['title'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['content'] = content;
    data['content1'] = content1;
    data['title'] = title;
    return data;
  }
}
